﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Diagnostics;

namespace LS.Screening.Core
{
    /// <summary>
    /// 审计日志拦截器
    /// </summary>
    public class GlobalAuditActionFilterAttribute : ActionFilterAttribute, IExceptionFilter
    {
        private string tag;
        private object parameters;
        private Stopwatch stopwatch;
        private Tuple<bool, AuditEnableAttribute> checkResult = null;
        private AuditLog auditLog;
        private readonly ILogger<GlobalAuditActionFilterAttribute> logger;

        public GlobalAuditActionFilterAttribute(ILogger<GlobalAuditActionFilterAttribute> logger)
        {
            this.logger = logger;
        }

        /// <summary>
        /// 1、OnActionExecuting
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);
            stopwatch = Stopwatch.StartNew();
            stopwatch.Start();
            tag = nameof(OnActionExecuting);
            parameters = context.ActionArguments;
        }

        /// <summary>
        /// 2、OnActionExecuted
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
            checkResult = context.CheckIsEnable<AuditEnableAttribute, AuditDisableAttribute>();
            if (checkResult?.Item1 == true && context.Exception == null)
            {
                stopwatch.Stop();
                auditLog = context.AddLog(checkResult.Item2, parameters, "");
                auditLog.Url = context.HttpContext.Request.Path.Value;
                auditLog.Tags += $",{tag}";
                auditLog.Tags += $",{nameof(OnActionExecuted)}";
                auditLog.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
                auditLog.IsSuccess = true;
                //logger.Info(checkResult.Item2.Remark, auditLog, checkResult.Item2.Tags.Split(','));
            }
        }

        /// <summary>
        /// 3、OnException
        /// </summary>
        /// <param name="context"></param>
        public void OnException(ExceptionContext context)
        {
            if (context.ExceptionHandled == false)
            {
                var exceptionLog = context.AddLog(checkResult.Item2?.AppName, parameters);
                exceptionLog.Tags += $",{nameof(OnException)}";
                //logger.Error(checkResult.Item2.Remark, exceptionLog, exceptionLog.Tags.Split(','));
                context.ExceptionHandled = true;
            }
        }
    }
}
